package com.campus.secondhand.security;

import java.io.IOException;
import java.util.Arrays;
import java.util.List;

import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
import org.springframework.stereotype.Component;
import org.springframework.util.AntPathMatcher;
import org.springframework.util.StringUtils;
import org.springframework.web.filter.OncePerRequestFilter;

import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;

/**
 * JWT认证过滤器，验证token有效性
 */
@Component
@RequiredArgsConstructor
@Slf4j
public class JwtAuthenticationFilter extends OncePerRequestFilter {

    private final JwtTokenProvider jwtTokenProvider;
    private final UserDetailsService userDetailsService;
    private final AntPathMatcher pathMatcher = new AntPathMatcher();

    // 定义不需要Token验证的URL路径
    private final List<String> excludedPaths = Arrays.asList(
            "/auth/login",
            "/auth/register",
            "/auth/verify-code/**",
            "/auth/forget-password",
            "/auth/refresh-token",
            "/auth/check-status",
            "/user/login",
            "/user/register",
            "/user/send-code",
            "/user/reset-password",
            "/user/check-status",
            "/schools/**",
            "/products/{id}",
            "/products/*/view",
            "/products/categories/**",
            "/requests/*/view",
            "/uploads/**",
            "/login",
            "/register",
            "/forgot-password",
            "/static/**",
            "/css/**",
            "/js/**",
            "/images/**",
            "/fonts/**",
            "/favicon.ico",
            "/",
            "/index.html");

    @Override
    protected boolean shouldNotFilter(HttpServletRequest request) {
        String path = request.getServletPath();
        String method = request.getMethod();

        // 允许GET方法的products路径不需要验证
        if (path.equals("/products") && "GET".equals(method)) {
            return true;
        }

        return excludedPaths.stream()
                .anyMatch(p -> pathMatcher.match(p, path));
    }

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
            throws ServletException, IOException {
        try {
            String jwt = parseJwt(request);
            String path = request.getServletPath();
            log.debug("请求路径: {}, JWT Token存在: {}", path, jwt != null ? "是" : "否");

            if (jwt != null && jwtTokenProvider.validateToken(jwt)) {
                String username = jwtTokenProvider.getUsernameFromToken(jwt);
                log.info("JWT Token 验证成功，用户名: {}, 请求路径: {}", username, path);

                UserDetails userDetails = userDetailsService.loadUserByUsername(username);
                UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(
                        userDetails, null, userDetails.getAuthorities());
                authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));

                SecurityContextHolder.getContext().setAuthentication(authentication);
                log.info("用户 {} 已认证并访问: {}", username, path);
            } else if (jwt != null) {
                log.warn("无效的JWT Token: {}, 请求路径: {}", jwt, path);
            } else {
                log.debug("没有提供JWT Token，请求路径: {}", path);
            }
        } catch (Exception e) {
            log.error("无法设置用户认证: {}", e.getMessage(), e);
        }

        filterChain.doFilter(request, response);
    }

    private String parseJwt(HttpServletRequest request) {
        String headerAuth = request.getHeader("Authorization");

        if (StringUtils.hasText(headerAuth) && headerAuth.startsWith("Bearer ")) {
            return headerAuth.substring(7);
        }

        return null;
    }
}